import { filterProperties } from '@/util'
import { Col, FormItem } from 'element-ui'

const elColManualBindKeys = ['span']
const elColKeys = [...Object.keys(Col.props)]
const elColAutoBindKeys = elColKeys.filter(key => !elColManualBindKeys.includes(key))

const elFormItemManualBindKeys = ['label', 'prop', 'rules', 'labelWidth', 'required']
const elFormItemKeys = [...Object.keys(FormItem.props)]
const elFormItemAutoBindKeys = elFormItemKeys.filter(key => !elFormItemManualBindKeys.includes(key))

const formItemAutoBindKeys = [
  'wrapCol',
  'wrapFormItem',
  'unwrap',
  'prefixConfig',
  'block',
  'placeholder',
  'prefixPick',
  'half',
  'tips',
  'hideLabel',
  'fixedSpan',
  ...elColKeys,
  ...elFormItemKeys
]

const formProperties = [
  'disabled',
  'size',
  'statusIcon',
  'inlineMessage',
  'autoLabelWidth',
  'hideRequiredAsterisk',
  '$emit',
  'validate',
  'clearValidate'
]

const formMethod = ['$emit', 'validate', 'clearValidate']

export default {
  name: 'FormInput',
  inject: {
    elForm: {
      default: {}
    },
    formItemGroup: {
      default: {}
    },
    formHolder: {
      default: {}
    }
  },
  provide() {
    return {
      elForm: this.proxyForm,
      formItemGroup: this
    }
  },
  props: {
    disabled: Boolean,
    fixedSpan: Number,
    wrapCol: {
      type: Boolean,
      default: true
    },
    wrapFormItem: {
      type: Boolean,
      default: true
    },
    unwrap: Boolean,
    half: Boolean,
    prefixConfig: Boolean,
    block: Boolean,
    placeholder: {
      type: [Boolean, String],
      default: true
    },
    formItemClass: String,
    prefixPick: Boolean,
    // el-form-item
    label: String,
    labelWidth: String,
    prop: String,
    hideLabel: Boolean,
    required: Boolean,
    rules: [Object, Array],
    error: String,
    validateStatus: String,
    for: String,
    inlineMessage: {
      type: [String, Boolean],
      default: ''
    },
    showMessage: {
      type: Boolean,
      default: true
    },
    size: String,
    trigger: {
      type: String,
      default: 'blur'
    },
    tips: String,
    // el-col
    span: {
      type: Number,
      default: 12
    },
    tag: {
      type: String,
      default: 'div'
    },
    offset: Number,
    pull: Number,
    push: Number,
    xs: [Number, Object],
    sm: [Number, Object],
    md: [Number, Object],
    lg: [Number, Object],
    xl: [Number, Object]
  },
  data() {
    const proxyForm = {}
    formProperties.forEach(key => {
      proxyForm[key] = null
    })
    return {
      proxyForm
    }
  },
  computed: {
    prefix() {
      if (this.prefixConfig) {
        return '请配置'
      } else if (this.prefixPick) {
        return '请选择'
      } else {
        return '请输入'
      }
    },
    message() {
      return `${this.prefix}${this.label?.replace('：', '') || ''}`
    },
    computeRules() {
      const rules = [...(this.rules || [])]
      const requireRule = rules.find(value => value.required)
      if (this.required || requireRule) {
        const requireRule = rules.find(value => value.required)
        if (requireRule) {
          // 有 ref 属性的 rule 不需要添加提示信息,由验证器提供必填信息
          if (!requireRule.ref) {
            requireRule.message = requireRule.message || this.message
          } else {
            requireRule.label = requireRule.label || this.label
          }
        } else {
          rules.unshift(this.getRequireRule())
        }
      }
      return rules.concat(this.getRules())
    },
    computeSpan() {
      return this.block ? 24 : this.span
    },
    formItemProps() {
      return filterProperties({ ...this.$props, ...this.$attrs }, formItemAutoBindKeys)
    },
    elFormItemProps() {
      return filterProperties({ ...this.$props, ...this.$attrs }, elFormItemAutoBindKeys)
    },
    elColProps() {
      return filterProperties({ ...this.$props, ...this.$attrs }, elColAutoBindKeys)
    },
    formCfg() {
      const formConfig = {
        disabled: this.disabled
      }
      formProperties.forEach(key => {
        formConfig[key] = this.elForm[key]
      })
      return formConfig
    }
  },
  watch: {
    computeRules() {
      this.elForm?.clearValidate?.(this.prop)
    },
    formCfg: {
      immediate: true,
      handler() {
        this.proxyForm.disabled = this.formHolder.enabledFields?.includes(this.prop)
          ? false
          : (this.elForm || {}).disabled
        formProperties.forEach(key => {
          if (key !== 'disabled') {
            if (formMethod.includes(key)) {
              this.proxyForm[key] = this.elForm[key]?.bind(this.elForm)
            } else {
              this.proxyForm[key] = this.elForm[key]
            }
          }
        })
      }
    }
  },
  methods: {
    getRules() {
      return []
    },
    getRequireRule() {
      return {
        required: true,
        trigger: this.trigger,
        message: this.message
      }
    }
  }
}
